/**
 * @file matvec.h
 * @author Yi Zhang (zhangyiss@icloud.com)
 * @brief  Useful functions for manipulating 2-D and 3-D tensors and vectors.
 * @version 1.0
 * @date 2021-12-27
 * 
 * @copyright Copyright (c) 2021
 * 
 */

#ifndef _MATVEC_H
#define _MATVEC_H

#include "complex"

/* =================== useful functions ===================== */

#define DETERMINANT_2X2(mat, det) \
{ \
    det = mat[0][0]*mat[1][1] - mat[0][1]*mat[1][0]; \
}

#define SCALE_ADJOINT_2X2(mat, scale, out) \
{ \
   out[0][0] =  (scale)*mat[1][1]; \
   out[1][0] = -(scale)*mat[1][0]; \
   out[0][1] = -(scale)*mat[0][1]; \
   out[1][1] =  (scale)*mat[0][0]; \
}

#define INVERT_2X2(mat, det, out) \
{ \
    DETERMINANT_2X2(mat, det); \
    (det) = 1.0/det; \
    SCALE_ADJOINT_2X2(mat, det, out); \
}

#define MAT_PRODUCT_2X2(a, b, c) \
{ \
    c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0];	\
    c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1];	\
    c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0];	\
    c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1];	\
}

#define MAT_VEC_2X2(a, b, c) \
{ \
    c[0] = a[0][0]*b[0]+a[0][1]*b[1];	\
    c[1] = a[1][0]*b[0]+a[1][1]*b[1];	\
}

#define C2R_2X2(c, creal, cimag) \
{ \
    creal[0][0] = c[0][0].real(); \
    creal[0][1] = c[0][1].real(); \
    creal[1][0] = c[1][0].real(); \
    creal[1][1] = c[1][1].real(); \
    cimag[0][0] = c[0][0].imag(); \
    cimag[0][1] = c[0][1].imag(); \
    cimag[1][0] = c[1][0].imag(); \
    cimag[1][1] = c[1][1].imag(); \
}

#define COPY_2X2(a, b) \
{ \
    b[0][0] = a[0][0]; \
    b[0][1] = a[0][1]; \
    b[1][0] = a[1][0]; \
    b[1][1] = a[1][1]; \
}

/* =================== useful functions ===================== */

#endif // _MATVEC_H